﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using MilitaryPluginInterface;

namespace _0912089
{
    public class PlayingScreen : ComponentView
    {
        Game1 _game;
        List<Team> _teams = new List<Team>();
        Map _map;
        GameBase.MapInfo _mapInfo;

        bool isLeftMouseClick = false;
        bool isRightMouseClick = false;
        bool isKeyAPressed = false;
        bool isKeyEscPressed = false;
        bool isPausedGame = false;

        Texture2D dot;
        Vector2 leftMousePressPosition = Vector2.Zero;
        Vector2 leftMouseDragPosition = Vector2.Zero;

        List<Military> militariesChosen = new List<Military>();

        ComponentView _exitPanel;
        Button _yes;
        Button _no; 
        Label _text;

        ImageView _win;
        ImageView _lose;
        Label _textRestart;
        Button _yesRestart;
        Button _noRestart;
        ComponentView _restartPanel;

        public PlayingScreen(Game1 game, GameBase.MapInfo mapInfo)
        {
            MediaPlayer.Stop();

            _game = game;
            _mapInfo = mapInfo;

            GameBase.Constant.maxTeam = mapInfo.Positions.Count;
            Team.initAll();
            for (int i = 0; i < GameBase.Constant.maxTeam; i++)
                _teams.Add(Team.getTeamAtIndex(i));

            initAllTeam(mapInfo);

            _map = new Map(mapInfo.Background);

            dot = GameBase.Constant.content.Load<Texture2D>(@"Resources/dot");

            initMessageBox();
            initEndGameLayout();
            initRestartMessageBox();
        }

        private void initAllTeam(GameBase.MapInfo mapInfo)
        {
            for (int i = 0; i < _teams.Count; i++)
            {
                Factory factory = new Factory(@"Resources/factory", mapInfo.Positions[i], mapInfo.Positions[i]);
                factory.IsRight = mapInfo.Orientations[i];
                factory.Position = mapInfo.Positions[i];

                float X = factory.Position.X;
                float Y = factory.Position.Y;
                if (factory.Position.X > GameBase.Constant.screenWidth - factory.Size.X)
                    X = GameBase.Constant.screenWidth - factory.Size.X;
                if (factory.Position.Y > GameBase.Constant.screenHeight - factory.Size.Y)
                    Y = GameBase.Constant.screenHeight - factory.Size.Y;
                factory.Position = new Vector2(X, Y);

                factory.TargetPosition = mapInfo.Positions[i] + factory.Size / 2;

                _teams[i].buildFactory(factory);
                _teams[i].Hero = factory.produceHeroImmediately();
            }
        }

        private void initRestartMessageBox()
        {
            _textRestart = new Label(@"Resources/fontNormal", @"Do you want to restart mission ?", new Vector2(25, 25), Color.Blue, 0.75f);
            _yesRestart = new Button(@"Resources/yes", new Vector2(25, 100), 0.5f);
            _noRestart = new Button(@"Resources/no", new Vector2(250, 100), 0.5f);
            _restartPanel = new ComponentView(@"Resources/panel", Vector2.Zero, new Vector2(500, 200));
            _restartPanel.Alpha = 0.4f;
            _restartPanel.Position = (new Vector2(GameBase.Constant.screenWidth, GameBase.Constant.screenHeight+100) - _restartPanel.Size) / 2;

            _restartPanel.addToSubView(_textRestart);
            _restartPanel.addToSubView(_yesRestart);
            _restartPanel.addToSubView(_noRestart);
            _restartPanel.Visible = false;
            this.addToSubView(_restartPanel);
        }

        private void initEndGameLayout()
        {
            _win = new ImageView(@"Resources/complete", Vector2.Zero, 1);
            _win.Position = (new Vector2(GameBase.Constant.screenWidth, GameBase.Constant.screenHeight - 300) - _win.Size) / 2;
            _win.Visible = false;
            _lose = new ImageView(@"Resources/fail", Vector2.Zero, 1);
            _lose.Position = (new Vector2(GameBase.Constant.screenWidth, GameBase.Constant.screenHeight - 300) - _lose.Size) / 2;
            _lose.Visible = false;

            this.addToSubView(_win);
            this.addToSubView(_lose);
        }

        private void initMessageBox()
        {
            _exitPanel = new ComponentView(@"Resources/panel", new Vector2(1400, 250), new Vector2(400, 250));
            _exitPanel.Position = (new Vector2(GameBase.Constant.screenWidth, GameBase.Constant.screenHeight) - _exitPanel.Size) / 2;
            _exitPanel.Alpha = 0.4f;
            //_exitPanel.Action = new MoveAction(_exitPanel, new Vector2(750, 250), 10f, 4f);

            _yes = new Button(@"Resources/yes", new Vector2(_exitPanel.Size.X / 2 - 105, _exitPanel.Size.Y - 70), 0.5f);
            _no = new Button(@"Resources/no", new Vector2(_exitPanel.Size.X / 2 - 105, _exitPanel.Size.Y - 140), 0.5f);
            _text = new Label(@"Resources/fontNormal", @"Do you want to exit game ?", new Vector2(20, 30), Color.Blue, 0.7f);

            _exitPanel.addToSubView(_yes);
            _exitPanel.addToSubView(_no);
            _exitPanel.addToSubView(_text);

            this.addToSubView(_exitPanel);
            _exitPanel.Visible = false;
        }

        public override void update(GameTime gameTime)
        {
            base.update(gameTime);

            MouseState ms = Mouse.GetState();
            KeyboardState kbs = Keyboard.GetState();
            Vector2 targetPos = new Vector2(ms.X, ms.Y);

            #region Keyboard processing
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                isKeyEscPressed = true;
            if (Keyboard.GetState().IsKeyUp(Keys.Escape) && isKeyEscPressed)
            {
                isKeyEscPressed = false;
                _exitPanel.Visible = isPausedGame = !_exitPanel.Visible;
            }
            if (kbs.IsKeyDown(Keys.A))
                isKeyAPressed = true;
            if (kbs.IsKeyUp(Keys.A) && isKeyAPressed)
            {
                isKeyAPressed = false;
                foreach (Military military in militariesChosen)
                    military.IsAutoControl = true;
            }
            #endregion

            #region Mouse processing
            if (ms.LeftButton == ButtonState.Pressed)
            {
                isLeftMouseClick = true;
                if (flag)
                {
                    flag = false;
                    leftMousePressPosition = targetPos;

                    // set all last chosen militaries to Auto Attack
                    deSelectMilitaries();
                }
                leftMouseDragPosition = targetPos;

                // get all chosen militaries 
                militariesChosen = getChosenMilitaries();
            }
            if (ms.RightButton == ButtonState.Pressed)
                isRightMouseClick = true;

            if (ms.LeftButton == ButtonState.Released && isLeftMouseClick)
            {
                isLeftMouseClick = false;
                flag = true;
                //_infantry.CurrentState = Military.SOLDIER_STATE.Idle;
                //_infantry.Attack(targetPos);

                if (_yes.isContainPoint(targetPos) && _exitPanel.Visible)
                {
                    goToMenuScreen();
                    return;
                }
                if (_no.isContainPoint(targetPos) && _exitPanel.Visible)
                    _exitPanel.Visible = isPausedGame = false;
                if (_yesRestart.isContainPoint(targetPos) && _restartPanel.Visible)
                {
                    restartMission();
                }
                if (_noRestart.isContainPoint(targetPos) && _restartPanel.Visible)
                {
                    goToMenuScreen();
                    return;
                }
            }
            if (ms.RightButton == ButtonState.Released && isRightMouseClick)
            {
                isRightMouseClick = false;
                //_infantry.walkTo(targetPos);

                // control all chosen militaries to walk to target point. (right click)
                foreach (Military military in militariesChosen)
                {
                    Military enemy = getEnemyAtPoint(targetPos);
                    if (enemy != null)
                    {
                        military.attack(enemy);
                        enemy.IsTargetPerson = true;
                    }
                    else
                    {
                        military.IsAutoControl = false;
                        military.walkTo(targetPos);
                    }
                }
            }
            #endregion

            if (isPausedGame)
                return;

            foreach (Team team in _teams)
                team.update(gameTime);

            if (_teams[0].isLosed())
            {
                _lose.Visible = isPausedGame = true;
                _restartPanel.Visible = true;
            }
            for(int i = 1; i < _teams.Count;i++)
            {
                if (!_teams[i].isLosed())
                    break;
                _win.Visible = isPausedGame = true;
                _restartPanel.Visible = true;
            }
        }

        private void restartMission()
        {
            _lose.Visible = isPausedGame = _win.Visible = _restartPanel.Visible = false;

            foreach (Team team in _teams)
            {
                team.Factories.Clear();
                team.Infantries.Clear();
            }

            initAllTeam(_mapInfo);
        }

        private void goToMenuScreen()
        {
            Game1.currentGameScreen = Game1.GameScreen.Menu;
            _game.MenuScreen.playAnimation();
            Team.clearAllTeam();

            _restartPanel.Visible = false;

            MediaPlayer.Play(GameBase.Constant.backgroundMusic);
        }

        public override void draw(GameTime gameTime, SpriteBatch spriteBatch, Color color)
        {
            _map.draw(gameTime, spriteBatch, Color.White);

            foreach (Team team in _teams)
            {
                foreach (Military military in team.Infantries)
                    if (military.isDead())
                        military.draw(gameTime, spriteBatch, military.TeamOwner.MyColor);
            }
            foreach (Team team in _teams)
            {
                foreach (Factory factory in team.Factories)
                    factory.draw(gameTime, spriteBatch, factory.TeamOwner.MyColor);
            }
            foreach (Team team in _teams)
            {
                foreach (Military military in team.Infantries)
                    if (!military.isDead())
                        military.draw(gameTime, spriteBatch, military.TeamOwner.MyColor);
            }
            foreach (Team team in _teams)
            {
                team.Hero.draw(gameTime, spriteBatch, team.MyColor);
            }
            foreach (Team team in _teams)
            {
                foreach (Military military in team.Infantries)
                    if (military.isAttacking())
                        military.Bullet.draw(gameTime, spriteBatch, Color.White);
            }

            if (isLeftMouseClick)
            {
                drawRectangle(spriteBatch, leftMousePressPosition, leftMouseDragPosition);
            }

            base.draw(gameTime, spriteBatch, color);
        }

        bool flag = true;

        private void drawRectangle(SpriteBatch spriteBatch, Vector2 beginPos, Vector2 endPos)
        {
            int numberOfDotsWidth = (int)Math.Abs(endPos.X - beginPos.X) / dot.Width;
            int numberOfDotsHeight = (int)Math.Abs(endPos.Y - beginPos.Y) / dot.Height;
            Vector2 minPosWidth = (beginPos.X < endPos.X) ? beginPos : endPos;
            Vector2 minPosHeight = (beginPos.Y < endPos.Y) ? beginPos : endPos;
            Color color = Color.LightGreen;
            for (int i = 0; i < numberOfDotsWidth; i++)
            {
                spriteBatch.Draw(dot, new Vector2(minPosWidth.X + i * dot.Width, beginPos.Y), color);
                spriteBatch.Draw(dot, new Vector2(minPosWidth.X + i * dot.Width, endPos.Y), color);
            }
            for (int i = 0; i < numberOfDotsHeight; i++)
            {
                spriteBatch.Draw(dot, new Vector2(beginPos.X, minPosHeight.Y + i * dot.Height), color);
                spriteBatch.Draw(dot, new Vector2(endPos.X, minPosHeight.Y + i * dot.Height), color);
            }
        }

        private List<Military> getChosenMilitaries()
        {
            List<Military> militaries = new List<Military>();
            float minX = (leftMousePressPosition.X < leftMouseDragPosition.X) ? leftMousePressPosition.X : leftMouseDragPosition.X;
            float maxX = (leftMousePressPosition.X > leftMouseDragPosition.X) ? leftMousePressPosition.X : leftMouseDragPosition.X;
            float minY = (leftMousePressPosition.Y < leftMouseDragPosition.Y) ? leftMousePressPosition.Y : leftMouseDragPosition.Y;
            float maxY = (leftMousePressPosition.Y > leftMouseDragPosition.Y) ? leftMousePressPosition.Y : leftMouseDragPosition.Y;
            Vector2 beginRectPoint = new Vector2(minX, minY);
            Vector2 endRectPoint = new Vector2(maxX, maxY);

            Rectangle rect = new Rectangle((int)minX, (int)minY, (int)maxX - (int)minX, (int)maxY - (int)minY);

            foreach (Military military in _teams[0].Infantries)
            {
                if (military.isInRect(rect))
                {
                    military.IsChosen = true;
                    militaries.Add(military);
                }
            }
            if (_teams[0].Hero.isInRect(rect))
            {
                _teams[0].Hero.IsChosen = true;
                militaries.Add(_teams[0].Hero);
            }
            return militaries;
        }

        private void deSelectMilitaries()
        {
            foreach (Military military in militariesChosen)
            {
                military.IsChosen = false;
                military.IsAutoControl = true;
            }
        }

        private Military getEnemyAtPoint(Vector2 point)
        {
            for (int i = 1; i < _teams.Count; i++)
            {
                Team team = _teams[i];
                if (team.Hero.isInPoint(point))
                    return team.Hero;
                foreach (Military militaryTarget in team.Infantries)
                    if (militaryTarget.isInPoint(point))
                    {
                        return militaryTarget;
                    }
            }
            return null;
        }
    }
}
